#include "ServerHttp.h"
#include "ServerHttpStatic.h"
#include "ServerTask.h"
#include "ServerStress.h"
#include "ServerCase.h"
#include "ServerSocksProxy.h"
#include "ServerHook.h"
#include "SheepsFactory.h"
#include <algorithm>

#ifdef __WINDOWS__
#include "io.h"
#include "direct.h"
#else
#include <dirent.h>
#include <unistd.h>
#endif


typedef int (*serverConsole_cmd_cb) (HSOCKET hsock, cJSON* root, cJSON* res);

enum {
	ERROR_TOKEN = -5,
	ERROR_PASSWORD = -4,
	ERROR_OPRAO = -3,
	ERROR_MEMRAY = -2,
	ERROR_PRAM = -1,
	ERROR_OK = 0,
	ERROR_TASKID = 101,
	ERROR_TASK_NOT_EXIST = 102,
	ERROR_PROJECT_NOT_EXIST = 103,
	ERROR_INDEX_ERROR = 104,
};

std::map<int, std::string> ErrorTable = {
	{ERROR_OK, "OK"},
	{ERROR_PRAM, "参数错误"},
	{ERROR_MEMRAY, "内存错误"},
	{ERROR_OPRAO, "操作失败"},
	{ERROR_TASKID, "任务id分配失败"},
	{ERROR_TASK_NOT_EXIST, "任务不存在"},
	{ERROR_PROJECT_NOT_EXIST, "项目不存在"},
	{ERROR_INDEX_ERROR, "下标错误"},
	{ERROR_PASSWORD, "账号或密码错误"},
	{ERROR_TOKEN, "token无效"}
};

static void set_error_info(cJSON* res, int ret)
{
	std::map<int, std::string>::iterator iter;
	iter = ErrorTable.find(ret);
	if (iter != ErrorTable.end()) {
		cJSON_AddStringToObject(res, "ret", iter->second.c_str());
	}
	else {
		cJSON_AddNumberToObject(res, "ret", ret);
	}
}

static void send_console_msg(HSOCKET hsock, cJSON* res, int ret)
{
	set_error_info(res, ret);

	int len = 0;
	char* data = cJSON_PrintUnformatted(res, &len);
	char buf[128] = { 0x0 };
	int n = snprintf(buf, sizeof(buf), "HTTP/1.1 %d OK\r\nAccess-Control-Allow-Origin:*\r\nContent-Type: application/json\r\nContent-Length: %d\r\n\r\n", ret == -99 ? 404 : 200, len);
	HsocketSend(hsock, buf, n);
	HsocketSend(hsock, data, len);
	cJSON_free(data);
	LOG(slogid, LOG_DEBUG, "%s:%d ret[%d]\n", __func__, __LINE__, ret);
}

static int do_agent_list(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* array = cJSON_CreateArray();
	if (array == NULL)
		return -1;

	cJSON_AddItemToObject(res, "data", array);

	cJSON* projectid = cJSON_GetObjectItem(root, "project_id");
	cJSON* groupid = cJSON_GetObjectItem(root, "group_id");

	int total = 0, nosuccess = 0, successed = 0, failed = 0;
	char addr[48] = { 0x0 };

	t_project_config* projectcfg;
	t_agent_group* group;
	t_sheeps_agent* agent;
	std::map<std::string, t_agent_group*>::iterator iter_group;
	std::map<HSOCKET, t_sheeps_agent*>::iterator iter_agent;
	for (int i = 0; i != int(ProjectConfig.size()); ++i) {
		if (projectid && cJSON_IsNumber(projectid) && projectid->valueint != i) {
			continue;
		}
		projectcfg = ProjectConfig[i];
		for (iter_group = projectcfg->groups.begin(); iter_group != projectcfg->groups.end(); ++iter_group) {
			if (groupid && cJSON_IsString(groupid) && strcmp(groupid->valuestring, iter_group->first.c_str()) != 0 )
				continue;
			group = iter_group->second;
			for (iter_agent = group->agents->begin(); iter_agent != group->agents->end(); ++iter_agent) {
				agent = iter_agent->second;
				cJSON* item = cJSON_CreateObject();
				if (item == NULL)
					continue;

				memset(addr, 0, sizeof(addr));
				const char* p = strchr(agent->ip, ':');
				snprintf(addr, sizeof(addr), p ? "[%s]:%d" : "%s:%d", agent->ip, agent->port);
				cJSON_AddStringToObject(item, "addr", addr);
				cJSON_AddNumberToObject(item, "cpu", agent->cpu);
				cJSON_AddNumberToObject(item, "cpu_cast", agent->cpu_cast);
				cJSON_AddNumberToObject(item, "mem", agent->mem_total);
				cJSON_AddNumberToObject(item, "mem_cast", agent->mem_cast);
				cJSON_AddNumberToObject(item, "network", agent->adapter);
				cJSON_AddNumberToObject(item, "network_cast", agent->adapter_cast);
				cJSON_AddNumberToObject(item, "ready", agent->ready);
				cJSON_AddNumberToObject(item, "project_id", agent->projectid);
				cJSON_AddStringToObject(item, "group_id", agent->groupid);
				char prokey[4] = { 0x0 };
				snprintf(prokey, sizeof(prokey), "%d", agent->projectid);
				cJSON_AddStringToObject(item, "project_name", config_get_string_value("project", prokey, "未配置"));
				cJSON_AddItemToArray(array, item);
				total++;
				if (agent->ready == AGENT_DEFAULT) nosuccess++;
				else if (agent->ready == AGENT_READY) successed++;
				else if (agent->ready == AGENT_FAIL) failed++;
			}
		}
	}

	cJSON_AddNumberToObject(res, "total", total);
	cJSON_AddNumberToObject(res, "not_ready", nosuccess);
	cJSON_AddNumberToObject(res, "ready", successed);
	cJSON_AddNumberToObject(res, "fail", failed);
	return 0;
}

static bool do_console_taskid_group(uint8_t taskid, const char* groupid)
{
	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(taskid);
	if (!taskcfg) return false;

	if (taskcfg->taskState == STATE_UNSTART || taskcfg->taskState == STATE_STOP)
	{
		snprintf(taskcfg->groupID, sizeof(taskcfg->groupID), "%s", groupid);
	}
	return true;
}

static int do_console_tasklist_group(HSOCKET hsock, cJSON* res, cJSON* tasklist, const char* groupid)
{
	cJSON* failedlist = cJSON_CreateArray();
	if (failedlist == NULL) return -1;
	cJSON_AddArrayToObject(res, "failed");

	for (int i = 0; i < cJSON_GetArraySize(tasklist); i++)
	{
		cJSON* taskid = cJSON_GetArrayItem(tasklist, i);
		if (!cJSON_IsNumber(taskid)) continue;

		if (!do_console_taskid_group(taskid->valueint, groupid))
		{
			cJSON_AddItemToArray(failedlist, cJSON_CreateNumber(taskid->valueint));
		}
	}
	return 0;
}

static int do_console_task_group(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* groupid = cJSON_GetObjectItem(root, "group_id");
	cJSON* taskid = cJSON_GetObjectItem(root, "task_id");
	if (groupid == NULL || taskid == NULL || !cJSON_IsString(groupid)|| (!cJSON_IsNumber(taskid) && !cJSON_IsArray(taskid)))
		return -1;
	if (cJSON_IsArray(taskid))
		return do_console_tasklist_group(hsock, res, taskid, groupid->valuestring);

	do_console_taskid_group(taskid->valueint, groupid->valuestring);
	return 0;
}

static bool do_console_taskid_log(uint8_t taskid, int loglevel)
{
	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(taskid);
	if (!taskcfg) return false;

	taskcfg->logLevel = loglevel;
	if (taskcfg->taskState == STATE_RUNING)
	{
		char buf[128] = { 0x0 };
		int n = snprintf(buf + 8, sizeof(buf) - 8, "{\"LogLevel\":%d, \"TaskID\":%d}", loglevel, taskid);
		*(int*)buf = n + 8;
		*(int*)(buf + 4) = S2C_Task_Log_Level;

		t_project_config* projectcfg;
		t_agent_group* group;
		std::map<std::string, t_agent_group*>::iterator iter_group;
		std::map<HSOCKET, t_sheeps_agent*>::iterator iter_agent;
		for (size_t i = 0; i != ProjectConfig.size(); ++i) {
			projectcfg = ProjectConfig[i];
			for (iter_group = projectcfg->groups.begin(); iter_group != projectcfg->groups.end(); ++iter_group) {
				group = iter_group->second;
				for (iter_agent = group->agents->begin(); iter_agent != group->agents->end(); ++iter_agent) {
					HsocketSend(iter_agent->first, buf, n + 8);
				}
			}
		}
	}
	return true;
}

static int do_console_tasklist_log(HSOCKET hsock, cJSON* res, cJSON* tasklist, int loglevel)
{
	cJSON* failedlist = cJSON_CreateArray();
	if (failedlist == NULL) return -1;
	cJSON_AddArrayToObject(res, "failed");

	for (int i = 0; i < cJSON_GetArraySize(tasklist); i++)
	{
		cJSON* taskid = cJSON_GetArrayItem(tasklist, i);
		if (!cJSON_IsNumber(taskid)) continue;

		if (!do_console_taskid_log(taskid->valueint, loglevel))
		{
			cJSON_AddItemToArray(failedlist, cJSON_CreateNumber(taskid->valueint));
		}
	}
	return 0;
}

static int do_console_task_log_level(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* level = cJSON_GetObjectItem(root, "log_level");
	cJSON* taskid = cJSON_GetObjectItem(root, "task_id");
	if (level == NULL || taskid == NULL || level->type != cJSON_Number || (!cJSON_IsNumber(taskid) && !cJSON_IsArray(taskid)))
		return -1;
	if (cJSON_IsArray(taskid))
		return do_console_tasklist_log(hsock, res, taskid, level->valueint);

	do_console_taskid_log(taskid->valueint, level->valueint);
	return 0;
}

static void do_console_task_change_replay(hServerTaskConfig taskcfg, cJSON* array)
{
	std::list<Readdr*>::iterator itr;
	for (itr = taskcfg->replayAddr->begin(); itr != taskcfg->replayAddr->end(); ++itr) {
		free(*itr);
	}
	taskcfg->replayAddr->clear();
	taskcfg->changeAddr->clear();
	if (array != NULL && array->type == cJSON_Array)
	{
		for (int i = 0; i < cJSON_GetArraySize(array); i++)
		{
			cJSON* item = cJSON_GetArrayItem(array, i);
			if (item == NULL || item->type != cJSON_Object)
				continue;

			cJSON* src = cJSON_GetObjectItem(item, "src");
			if (src == NULL || src->type != cJSON_String)
				continue;
			Readdr* addr = (Readdr*)malloc(sizeof(Readdr));
			if (addr == NULL)
			{
				LOG(slogid, LOG_ERROR, "%s:%d malloc error\r\n", __func__, __LINE__);
				continue;
			}
			memset(addr, 0x0, sizeof(Readdr));
			snprintf(addr->srcAddr, sizeof(addr->srcAddr), "%s", src->valuestring);

			cJSON* dst = cJSON_GetObjectItem(item, "dst");
			if (dst != NULL && src->type == cJSON_String)
			{
				snprintf(addr->dstAddr, sizeof(addr->dstAddr), "%s", dst->valuestring);
				taskcfg->changeAddr->insert(std::pair<std::string, Readdr*>(std::string(src->valuestring), addr));
			}
			taskcfg->replayAddr->push_back(addr);
		}
	}
}

static int do_console_task_change(HSOCKET hsock, cJSON* taskid, cJSON* projectid, cJSON* groupid, cJSON* total,
	cJSON* once, cJSON* space, cJSON* loop, cJSON* ignor, cJSON* dbfile, cJSON* des, cJSON* parms,
	cJSON* parms_server ,cJSON* array, cJSON* log_level, cJSON* log_report)
{
	if (!taskid || !cJSON_IsNumber(taskid))
		return -1;
	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(taskid->valueint);
	if (!taskcfg) return 102;
	if (projectid && cJSON_IsNumber(projectid))
	{
		taskcfg->projectID = projectid->valueint;
		char prokey[4] = { 0x0 };
		snprintf(prokey, sizeof(prokey), "%d", taskcfg->projectID);
		snprintf(taskcfg->projectName, sizeof(taskcfg->projectName), "%s", config_get_string_value("project", prokey, "未配置"));
	}
	if (groupid && cJSON_IsString(groupid)) snprintf(taskcfg->groupID, sizeof(taskcfg->groupID), "%s", groupid->valuestring);
	if (total && cJSON_IsNumber(total)) taskcfg->totalUser = total->valueint;
	if (once && cJSON_IsNumber(once)) taskcfg->onceUser = once->valueint;
	if (space && cJSON_IsNumber(space)) taskcfg->spaceTime = space->valueint;
	if (loop && cJSON_IsNumber(loop)) taskcfg->loopMode = loop->valueint;
	if (ignor && cJSON_IsNumber(ignor)) taskcfg->ignoreErr = ignor->valueint == 0 ? false : true;
	if (des && cJSON_IsString(des)) snprintf(taskcfg->taskDes, sizeof(taskcfg->taskDes), "%s", des->valuestring);
	if (log_level && cJSON_IsNumber(log_level)) taskcfg->logLevel = log_level->valueint;
	if (log_report && cJSON_IsNumber(log_report)) taskcfg->report_log = log_report->valueint;
	if (parms && cJSON_IsString(parms)) { 
		char* parms1 = parms->valuestring;
		size_t len = strlen(parms1);
		if (len) {
			free(taskcfg->parms1);
			taskcfg->parms1 = (char*)malloc(len + 1);
			memcpy(taskcfg->parms1, parms1, len + 1);
		}
		else {
			*(taskcfg->parms1) = 0x0;
		}
	}
	if (parms_server && cJSON_IsString(parms_server)) {
		char* parms2 = parms_server->valuestring;
		size_t len = strlen(parms2);
		if (len) {
			free(taskcfg->parms2);
			taskcfg->parms2 = (char*)malloc(len + 1);
			memcpy(taskcfg->parms2, parms2, len + 1);
		}
		else {
			*(taskcfg->parms2) = 0x0;
		}
	}

	if (dbfile && cJSON_IsString(dbfile)) {
		snprintf(taskcfg->dbName, sizeof(taskcfg->dbName), "%s", dbfile->valuestring);
		do_console_task_change_replay(taskcfg, array);
	}
	return 0;
}

static int do_console_task_create(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* projectid = cJSON_GetObjectItem(root, "project_id");
	cJSON* groupid = cJSON_GetObjectItem(root, "group_id");
	cJSON* total = cJSON_GetObjectItem(root, "total_user");
	cJSON* once = cJSON_GetObjectItem(root, "once_user");
	cJSON* space = cJSON_GetObjectItem(root, "space_time");
	cJSON* loop = cJSON_GetObjectItem(root, "loop_mode");
	cJSON* ignor = cJSON_GetObjectItem(root, "ignor_error");
	cJSON* dbfile = cJSON_GetObjectItem(root, "db_file");
	cJSON* des = cJSON_GetObjectItem(root, "des");
	cJSON* parms = cJSON_GetObjectItem(root, "parms");
	cJSON* parms_server = cJSON_GetObjectItem(root, "parms2");
	cJSON* array = cJSON_GetObjectItem(root, "replay");
	cJSON* log_level = cJSON_GetObjectItem(root, "log_level");
	cJSON* log_report = cJSON_GetObjectItem(root, "log_report");
	cJSON* taskid = cJSON_GetObjectItem(root, "task_id");

	if (taskid)
		return do_console_task_change(hsock, taskid, projectid, groupid, total, once, space, loop, ignor, dbfile, des, parms, parms_server, array, log_level, log_report);

	if (!projectid|| !groupid || !total || !once || !space || !loop || !ignor || !dbfile || !des || !parms || !parms_server || !array || !log_level || !log_report ||
		!cJSON_IsNumber(projectid) || !cJSON_IsString(groupid) || !cJSON_IsNumber(total) || !cJSON_IsNumber(once) || !cJSON_IsNumber(space) ||
		!cJSON_IsNumber(loop) || !cJSON_IsNumber(ignor) || !cJSON_IsString(dbfile) || !cJSON_IsString(des) || !cJSON_IsString(parms) || 
		!cJSON_IsString(parms_server) || !cJSON_IsArray(array) || !cJSON_IsNumber(log_level) || !cJSON_IsNumber(log_report)){
		return -1;
	}

	hServerTaskConfig task = (hServerTaskConfig)malloc(sizeof(ServerTaskConfig));
	if (task == NULL)
		return -2;
	memset(task, 0x0, sizeof(ServerTaskConfig));

	task->taskID = task_id_pool_get_id();
	if (task->taskID == 0) {
		free(task);
		return -3;
	}
	task_code_get(task->taskCode);
	task->projectID = projectid->valueint;
	snprintf(task->groupID, sizeof(task->groupID), "%s", groupid->valuestring);
	char prokey[4] = { 0x0 };
	snprintf(prokey, sizeof(prokey), "%d", task->projectID);
	snprintf(task->projectName, sizeof(task->projectName), "%s", config_get_string_value("project", prokey, "未配置"));

	task->totalUser = total->valueint;
	task->onceUser = once->valueint;
	task->spaceTime = space->valueint;
	task->loopMode = loop->valueint;
	task->ignoreErr = ignor->valueint == 0 ? false : true;
	task->logLevel = log_level->valueint;
	task->report_log = log_report->valueint;
	size_t parms_len = strlen(parms->valuestring);
	task->parms1 = (char*)malloc(parms_len + 1);
	if (!task->parms1) {
		free(task);
		return -4;
	}
	memcpy(task->parms1, parms->valuestring, parms_len + 1);

	parms_len = strlen(parms_server->valuestring);
	task->parms2 = (char*)malloc(parms_len + 1);
	if (!task->parms2) {
		free(task->parms1);
		free(task);
		return -5;
	}
	memcpy(task->parms2, parms_server->valuestring, parms_len + 1);

	snprintf(task->dbName, sizeof(task->dbName), "%s", dbfile->valuestring);
	snprintf(task->taskDes, sizeof(task->taskDes), "%s", des->valuestring);
	task->replayAddr = new(std::nothrow) std::list<Readdr*>;
	if (task->replayAddr == NULL){
		task_id_pool_push_back(task->taskID);
		free(task);
		return -2;
	}
	task->changeAddr = new(std::nothrow) std::map<std::string, Readdr*>;
	if (task->changeAddr == NULL){
		task_id_pool_push_back(task->taskID);
		delete task->replayAddr;
		free(task->parms1);
		free(task->parms2);
		free(task);
		return -2;
	}

	for (int i = 0; i < cJSON_GetArraySize(array); i++){
		cJSON* item = cJSON_GetArrayItem(array, i);
		if (!item || !cJSON_IsObject(item))
			continue;

		cJSON* src = cJSON_GetObjectItem(item, "src");
		if (!src || !cJSON_IsString(src))
			continue;
		Readdr* addr = (Readdr*)malloc(sizeof(Readdr));
		if (addr == NULL){
			LOG(slogid, LOG_ERROR, "%s:%d malloc error\r\n", __func__, __LINE__);
			continue;
		}
		memset(addr, 0x0, sizeof(Readdr));
		snprintf(addr->srcAddr, sizeof(addr->srcAddr), "%s", src->valuestring);
		cJSON* dst = cJSON_GetObjectItem(item, "dst");
		if (dst && cJSON_IsString(dst) && *(dst->valuestring) != 0x0){
			snprintf(addr->dstAddr, sizeof(addr->dstAddr), "%s", dst->valuestring);
			task->changeAddr->insert(std::pair<std::string, Readdr*>(std::string(src->valuestring), addr));
		}
		task->replayAddr->push_back(addr);
	}
	insert_server_taskcfg(task->taskID, task);

	cJSON_AddNumberToObject(res, "task_id", task->taskID);
	return 0;
}

static void do_consol_task_info_to_json(cJSON* item, hServerTaskConfig taskcfg) {
	cJSON_AddNumberToObject(item, "task_id", taskcfg->taskID);
	cJSON_AddNumberToObject(item, "state", taskcfg->taskState);
	if (taskcfg->taskState == 1)
	{
		hServerTaskRun taskrun = taskcfg->taskrun;
		cJSON_AddNumberToObject(item, "left_user", taskcfg->totalUser - taskrun->UserActiveCount);
		cJSON_AddNumberToObject(item, "alive", taskrun->UserActiveCount - taskrun->UserDeadCount);
		cJSON_AddNumberToObject(item, "online", taskrun->UserOnlineCount);

	}
	else
	{
		cJSON_AddNumberToObject(item, "left_user", taskcfg->totalUser);
		cJSON_AddNumberToObject(item, "alive", 0);
		cJSON_AddNumberToObject(item, "online", 0);
	}

	cJSON_AddStringToObject(item, "des", taskcfg->taskDes);
	cJSON_AddNumberToObject(item, "project_id", taskcfg->projectID);
	cJSON_AddStringToObject(item, "project_name", taskcfg->projectName);
	cJSON_AddStringToObject(item, "group_id", taskcfg->groupID);
	cJSON_AddNumberToObject(item, "total_user", taskcfg->totalUser);
	cJSON_AddNumberToObject(item, "once_user", taskcfg->onceUser);
	cJSON_AddNumberToObject(item, "space_time", taskcfg->spaceTime);
	cJSON_AddNumberToObject(item, "loop_mode", taskcfg->loopMode);
	cJSON_AddNumberToObject(item, "ignor_error", taskcfg->ignoreErr);
	cJSON_AddNumberToObject(item, "log_level", taskcfg->logLevel);
	cJSON_AddNumberToObject(item, "log_report", taskcfg->report_log);
	cJSON_AddStringToObject(item, "parms", taskcfg->parms1);
	cJSON_AddStringToObject(item, "parms2", taskcfg->parms2);
	cJSON_AddStringToObject(item, "db_file", taskcfg->dbName);
	cJSON* replay = cJSON_CreateArray();
	if (replay == NULL){
		return;
	}
	cJSON_AddItemToObject(item, "replay", replay);
	std::list<Readdr*>::iterator it = taskcfg->replayAddr->begin();
	for (; it != taskcfg->replayAddr->end(); ++it)
	{
		cJSON* item = cJSON_CreateObject();
		if (item == NULL) continue;
		cJSON_AddStringToObject(item, "src", (*it)->srcAddr);
		cJSON_AddStringToObject(item, "dst", (*it)->dstAddr);
		cJSON_AddItemToArray(replay, item);
	}
}

static int do_console_task_info(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* taskid = cJSON_GetObjectItem(root, "task_id");
	if (taskid == NULL || taskid->type != cJSON_Number)
		return -1;

	hServerTaskConfig info = get_server_taskcfg_by_id(taskid->valueint);
	if (!info) return 102;
	cJSON* data = cJSON_CreateObject();
	if (data == NULL)
		return -2;
	cJSON_AddItemToObject(res, "data", data);
	do_consol_task_info_to_json(data, info);
	return 0;
}

static bool do_console_taskid_user(uint8_t taskid, int usercount)
{
	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(taskid);
	if (taskcfg)
	{
		taskcfg->totalUser += usercount;
		if (taskcfg->totalUser < 0)
			taskcfg->totalUser = 0;
		else
			taskcfg->totalUser = taskcfg->totalUser;
	}
	return true;
}

static int do_console_tasklist_user(HSOCKET hsock, cJSON* res, cJSON* tasklist, int usercout)
{
	cJSON* failedlist = cJSON_CreateArray();
	if (failedlist == NULL) return -2;
	cJSON_AddArrayToObject(res, "failed");

	for (int i = 0; i < cJSON_GetArraySize(tasklist); i++)
	{
		cJSON* taskid = cJSON_GetArrayItem(tasklist, i);
		if (!cJSON_IsNumber(taskid)) continue;

		if (!do_console_taskid_user(taskid->valueint, usercout))
		{
			cJSON_AddItemToArray(failedlist, cJSON_CreateNumber(taskid->valueint));
		}
	}
	return 0;
}

static int do_console_task_user(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* taskid = cJSON_GetObjectItem(root, "task_id");
	cJSON* count = cJSON_GetObjectItem(root, "user_count");
	if (taskid == NULL || count == NULL || (!cJSON_IsNumber(taskid) && !cJSON_IsArray(taskid)) || count->type != cJSON_Number)
		return -1;
	if (cJSON_IsArray(taskid))
		return do_console_tasklist_user(hsock, res, taskid, count->valueint);
	if (do_console_taskid_user(taskid->valueint, count->valueint))
		return 0;
	return -3;
}

static bool do_console_taskid_delete(uint8_t taskid)
{
	ServerTaskCfgLock->lock();
	std::map<int, hServerTaskConfig>::iterator iter;
	iter = ServerTaskCfg->find(taskid);
	if (iter != ServerTaskCfg->end()){
		hServerTaskConfig taskcfg = iter->second;
		if (taskcfg->taskState != STATE_RUNING){
			task_id_pool_push_back(taskcfg->taskID);
			std::list<Readdr*>::iterator itr;
			for (itr = taskcfg->replayAddr->begin(); itr != taskcfg->replayAddr->end(); ++itr){
				free(*itr);
			}
			taskcfg->replayAddr->clear();
			delete taskcfg->replayAddr;
			taskcfg->changeAddr->clear();
			delete taskcfg->changeAddr;

			if (taskcfg->taskrun) {
				taskrun_clear(taskcfg->taskrun);
				free(taskcfg->taskrun);
			}

			free(taskcfg);
			ServerTaskCfg->erase(iter);
		}
	}
	ServerTaskCfgLock->unlock();
	return true;
}

static int do_console_tasklist_delete(HSOCKET hsock, cJSON* res, cJSON* tasklist)
{
	cJSON* failedlist = cJSON_CreateArray();
	if (failedlist == NULL) return -2;
	cJSON_AddArrayToObject(res, "failed");

	for (int i = 0; i < cJSON_GetArraySize(tasklist); i++)
	{
		cJSON* taskid = cJSON_GetArrayItem(tasklist, i);
		if (!cJSON_IsNumber(taskid)) continue;

		if (!do_console_taskid_delete(taskid->valueint))
		{
			cJSON_AddItemToArray(failedlist, cJSON_CreateNumber(taskid->valueint));
		}
	}
	return 0;
}

static int do_console_task_delete(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* taskid = cJSON_GetObjectItem(root, "task_id");
	if (taskid == NULL || (!cJSON_IsNumber(taskid) && !cJSON_IsArray(taskid)))
		return -1;
	if (cJSON_IsArray(taskid))
		return do_console_tasklist_delete(hsock, res, taskid);
	if (do_console_taskid_delete(taskid->valueint))
		return 0;
	return -3;
}

static int do_console_task_list(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* array = cJSON_CreateArray();
	if (array == NULL)
		return -2;

	cJSON_AddItemToObject(res, "data", array);

	cJSON* project = cJSON_GetObjectItem(root, "project_id");
	std::map<int, hServerTaskConfig>::iterator iter = ServerTaskCfg->begin();
	for (; iter != ServerTaskCfg->end(); ++iter)
	{
		hServerTaskConfig info = iter->second;
		if (project && cJSON_IsNumber(project) && project->valueint != info->projectID)
			continue;
		cJSON* item = cJSON_CreateObject();
		if (item == NULL)
			continue;
		do_consol_task_info_to_json(item, info);
		cJSON_AddItemToArray(array, item);
	}
	return 0;
}

static bool do_console_taskid_run(uint8_t taskid)
{
	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(taskid);
	if (taskcfg) {
		if (taskcfg->taskState != STATE_UNSTART && taskcfg->taskState != STATE_STOP)
			return false;
		task_run(taskcfg);
		return true;
	}
	return false;
}

static int do_console_tasklist_run(HSOCKET hsock, cJSON* res, cJSON* tasklist)
{
	cJSON* failedlist = cJSON_CreateArray();
	if (failedlist == NULL) return -2;
	cJSON_AddArrayToObject(res, "failed");

	for (int i = 0; i < cJSON_GetArraySize(tasklist); i++)
	{
		cJSON* taskid = cJSON_GetArrayItem(tasklist, i);
		if (!cJSON_IsNumber(taskid)) continue;

		if (!do_console_taskid_run(taskid->valueint))
		{
			cJSON_AddItemToArray(failedlist, cJSON_CreateNumber(taskid->valueint));
		}
	}
	return 0;
}

static int do_console_task_run(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* taskid = cJSON_GetObjectItem(root, "task_id");
	if (taskid == NULL || (!cJSON_IsNumber(taskid) && !cJSON_IsArray(taskid)))
		return -1;
	if (cJSON_IsArray(taskid))
		return do_console_tasklist_run(hsock, res, taskid);

	if (do_console_taskid_run(taskid->valueint))
		return 0;
	return -3;
}

static bool do_console_taskid_stop(uint8_t taskid)
{
	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(taskid);
	if (!taskcfg) return false;
	hServerTaskRun taskrun = taskcfg->taskrun;
	if (!taskrun) return false;
	task_push_over(taskrun, taskcfg);
	return true;
}

static int do_console_tasklist_stop(HSOCKET hsock, cJSON* res, cJSON* tasklist)
{
	cJSON* failedlist = cJSON_CreateArray();
	if (failedlist == NULL) return -2;
	cJSON_AddArrayToObject(res, "failed");

	for (int i = 0; i < cJSON_GetArraySize(tasklist); i++)
	{
		cJSON* taskid = cJSON_GetArrayItem(tasklist, i);
		if (!cJSON_IsNumber(taskid)) continue;

		if (!do_console_taskid_stop(taskid->valueint))
		{
			cJSON_AddItemToArray(failedlist, cJSON_CreateNumber(taskid->valueint));
		}
	}
	return 0;
}

static int do_console_task_stop(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* taskid = cJSON_GetObjectItem(root, "task_id");
	if (taskid == NULL || (!cJSON_IsNumber(taskid) && !cJSON_IsArray(taskid)))
		return -1;
	if (cJSON_IsArray(taskid))
		return do_console_tasklist_stop(hsock, res, taskid);

	if (!do_console_taskid_stop(taskid->valueint))
		return -3;
	return 0;
}

static int do_proxy_addr_list(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* array = cJSON_CreateArray();
	if (array == NULL)
		return -2;

	cJSON_AddItemToObject(res, "data", array);

	char addr[256] = { 0x0 };

	std::map<ServerProtocol*, std::string>::iterator iter = ProxyAddr->begin();
	for (; iter != ProxyAddr->end(); ++iter)
	{
		cJSON* item = cJSON_CreateObject();
		if (item == NULL)
			continue;

		memset(addr, 0, sizeof(addr));
		snprintf(addr, sizeof(addr), "%s", iter->second.c_str());
		cJSON_AddStringToObject(item, "addr", addr);
		cJSON_AddItemToArray(array, item);
	}
	return 0;
}

static int do_proxy_report_api(HSOCKET hsock, cJSON* root, cJSON* res){
		cJSON* array = cJSON_CreateArray();
	cJSON_AddItemToObject(res, "data", array);

	std::map<std::string, PorxyInfoApi*>::iterator iter;
	for (iter = ProxyApi.begin(); iter != ProxyApi.end(); ++iter) {
		PorxyInfoApi* info = iter->second;
		cJSON* item = cJSON_CreateObject();
		cJSON_AddStringToObject(item, "api", iter->first.c_str());
		if (info->send_count > 0) {
			cJSON_AddNumber64ToObject(item, "send_flow", info->send_flow);
			cJSON_AddNumberToObject(item, "send_count", info->send_count);
		}
		if (info->recv_count > 0) {
			cJSON_AddNumber64ToObject(item, "recv_flow", info->recv_flow);
			cJSON_AddNumberToObject(item, "recv_count", info->recv_count);
		}
		
		if (info->success || info->error) {
			cJSON_AddNumberToObject(item, "success", info->success);
			cJSON_AddNumberToObject(item, "error", info->error);
		}
		int size = info->sorted;
		if (size) {
			std::vector<int>* vec = info->vecData;
			cJSON_AddNumberToObject(item, "min", (*vec)[0]);
			cJSON_AddNumberToObject(item, "max", (*vec)[size - 1]);
			cJSON_AddNumberToObject(item, "10", (*vec)[int(size * 0.1)]);
			cJSON_AddNumberToObject(item, "20", (*vec)[int(size * 0.2)]);
			cJSON_AddNumberToObject(item, "30", (*vec)[int(size * 0.3)]);
			cJSON_AddNumberToObject(item, "40", (*vec)[int(size * 0.4)]);
			cJSON_AddNumberToObject(item, "50", (*vec)[int(size * 0.5)]);
			cJSON_AddNumberToObject(item, "60", (*vec)[int(size * 0.6)]);
			cJSON_AddNumberToObject(item, "70", (*vec)[int(size * 0.7)]);
			cJSON_AddNumberToObject(item, "80", (*vec)[int(size * 0.8)]);
			cJSON_AddNumberToObject(item, "90", (*vec)[int(size * 0.9)]);
		}
		cJSON_AddItemToArray(array, item);
	}
	return ERROR_OK;
}

static int do_case_addr_list(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* dbfile = cJSON_GetObjectItem(root, "db_file");
	if (dbfile == NULL || dbfile->type != cJSON_String || *(dbfile->valuestring) == 0x0)
		return -1;

	cJSON* data = cJSON_CreateObject();
	cJSON* array = cJSON_CreateArray();
	if (!array || !data)
	{
		if (data) cJSON_Delete(data);
		if (array) cJSON_Delete(array);
		return -2;
	}
	cJSON_AddItemToObject(res, "data", data);
	cJSON_AddItemToObject(data, "record_list", array);

	sqlite3* dbConn;
	char fullpath[256] = { 0x0 };
	snprintf(fullpath, sizeof(fullpath), "%s/%s", CasePath, dbfile->valuestring);
	sqlite3_open(fullpath, &dbConn);

	const char* sql = "select name from sqlite_sequence";
	sqlite3_stmt* stmt = NULL;
	int result = sqlite3_prepare_v2(dbConn, sql, -1, &stmt, NULL);
	if (result == SQLITE_OK)
	{
		char addr[128] = { 0x0 };
		while (sqlite3_step(stmt) == SQLITE_ROW)
		{
			const char* table = (const char*)sqlite3_column_text(stmt, 0);
			int ret = table_to_addr(table, addr, sizeof(addr));
			if (ret) {
				cJSON* item = cJSON_CreateObject();
				if (item == NULL)
					continue;
				cJSON_AddStringToObject(item, "addr", addr);
				cJSON_AddItemToArray(array, item);
			}
		}
	}
	sqlite3_finalize(stmt);

	sql = "select project_id,project,des from caseinfo limit 1";
	bool flag = false;
	const char* errmsg;
	result = sqlite3_prepare_v2(dbConn, sql, -1, &stmt, &errmsg);
	if (result == SQLITE_OK)
	{
		if (sqlite3_step(stmt) == SQLITE_ROW)
		{
			int projectid = sqlite3_column_int(stmt, 0);
			const char* project_name = (const char*)sqlite3_column_text(stmt, 1);
			const char* des = (const char*)sqlite3_column_text(stmt, 2);
			cJSON_AddItemToObject(data, "db_file", cJSON_CreateString(dbfile->valuestring));
			cJSON_AddItemToObject(data, "project_id", cJSON_CreateNumber(projectid));
			cJSON_AddItemToObject(data, "project", cJSON_CreateString(project_name));
			cJSON_AddItemToObject(data, "des", cJSON_CreateString(des));
			flag = true;
		}
	}
	else
	{
		//LOG(slogid, LOG_ERROR, "%s:%d sqlite3 error[%s]\r\n", __func__, __LINE__, errmsg);
	}
	sqlite3_finalize(stmt);
	sqlite3_close(dbConn);

	if (!flag)
	{
		cJSON_AddItemToObject(data, "db_file", cJSON_CreateString(dbfile->valuestring));
		cJSON_AddItemToObject(data, "project_id", cJSON_CreateNumber(0));
		cJSON_AddItemToObject(data, "project", cJSON_CreateString("默认"));
		cJSON_AddItemToObject(data, "des", cJSON_CreateString("无"));

	}
	return 0;
}

static int do_case_record_chang(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* record = cJSON_GetObjectItem(root, "record");
	if (record != NULL && (record->type == cJSON_True || record->type == cJSON_False))
	{
		Proxy_record = record->valueint == 0 ? false : true;
	}

	cJSON_AddBoolToObject(res, "record", Proxy_record);
	cJSON_AddNumberToObject(res, "left", (int)recordList->size());
	return 0;
}

static int do_case_record_set_filter(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* filter = cJSON_GetObjectItem(root, "filter");
	if (!filter || !cJSON_IsArray(filter)) {
		return -1;
	}
	record_filter->clear();
	int size = cJSON_GetArraySize(filter);
	for (int i = 0; i < size; i++){
		cJSON* item = cJSON_GetArrayItem(filter, i);
		if (cJSON_IsString(item)) {
			record_filter->insert(std::make_pair(item->valuestring, true));
		}
	}
	return 0;
}

static int do_case_record_get_filter(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* filter = cJSON_AddArrayToObject(res, "data");
	std::map<std::string, bool>::iterator iter;
	for (iter = record_filter->begin(); iter != record_filter->end(); iter++) {
		cJSON_AddItemToArray(filter, cJSON_CreateString(iter->first.c_str()));
	}
	return 0;
}

static int do_case_addr_delete(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* addr = cJSON_GetObjectItem(root, "addr");
	cJSON* dbfile = cJSON_GetObjectItem(root, "db_file");
	if (addr == NULL || dbfile == NULL || addr->type != cJSON_Array || dbfile->type != cJSON_String)
		return -1;

	char file[256] = { 0x0 };
	snprintf(file, sizeof(file), "%s/%s", CasePath, dbfile->valuestring);
	sqlite3* dbConn;
	sqlite3_open(file, &dbConn);

	char table[128] = { 0x0 };
	char sql[256] = { 0x0 };
	int size = cJSON_GetArraySize(addr);
	for (int i = 0; i < size; i++)
	{
		cJSON* item = cJSON_GetArrayItem(addr, i);
		int ret = addr_to_table(item->valuestring, table, sizeof(table));
		snprintf(sql, sizeof(sql), "DROP TABLE \"%s\"", table);
		if (ret) {
			char* errmsg;
			ret = sqlite3_exec(dbConn, sql, NULL, NULL, &errmsg);
			if (ret != SQLITE_OK)
			{
				LOG(slogid, LOG_ERROR, "%s:%d sqlite3 error[%s]\r\n", __func__, __LINE__, errmsg);
			}
		}
	}
	sqlite3_close(dbConn);
	return 0;
}

static void add_to_databse_filelist(cJSON* array, cJSON* project_id, const char* dbname)
{
	if (strcmp(".db", dbname + strlen(dbname) - 3) != 0)return;

	int projectid = project_id && cJSON_IsNumber(project_id) ? project_id->valueint : 0;
	char key[4] = { 0x0 };
	snprintf(key, sizeof(key), "%d", projectid);
	const char* project_name = config_get_string_value("project", key, "");

	if (project_id && cJSON_IsNumber(project_id) && strncmp(project_name, dbname, strlen(project_name)) != 0)
		return;

	char file[256] = { 0x0 };
	snprintf(file, sizeof(file), "%s/%s", CasePath, dbname);
	sqlite3* dbConn;
	sqlite3_open(file, &dbConn);
	const char* errmsg = NULL;
	char sql[512] = { 0x0 };
	snprintf(sql, sizeof(sql), "select project_id,project_name,des from caseinfo limit 1");
	sqlite3_stmt* stmt = NULL;
	bool flag = false;
	int result = sqlite3_prepare_v2(dbConn, sql, -1, &stmt, &errmsg);
	if (result == SQLITE_OK)
	{
		if (sqlite3_step(stmt) == SQLITE_ROW)
		{
			cJSON* item = cJSON_CreateObject();
			if (item)
			{
				projectid = sqlite3_column_int(stmt, 0);
				project_name = (const char*)sqlite3_column_text(stmt, 1);
				const char* des = (const char*)sqlite3_column_text(stmt, 2);
				cJSON_AddItemToObject(item, "db_file", cJSON_CreateString(dbname));
				cJSON_AddItemToObject(item, "project_id", cJSON_CreateNumber(projectid));
				cJSON_AddItemToObject(item, "project", cJSON_CreateString(project_name));
				cJSON_AddItemToObject(item, "des", cJSON_CreateString(des));
				cJSON_AddItemToArray(array, item);
				flag = true;
			}
		}
	}
	else
	{
		//LOG(slogid, LOG_ERROR, "%s:%d sqlite3 error[%s]\r\n", __func__, __LINE__, errmsg);
	}
	sqlite3_finalize(stmt);
	sqlite3_close(dbConn);

	if (!flag)
	{
		cJSON* item = cJSON_CreateObject();
		if (item)
		{
			cJSON_AddItemToObject(item, "db_file", cJSON_CreateString(dbname));
			cJSON_AddItemToObject(item, "project_id", cJSON_CreateNumber(projectid));
			cJSON_AddItemToObject(item, "project", cJSON_CreateString(project_name));
			cJSON_AddItemToObject(item, "des", cJSON_CreateString("无"));
			cJSON_AddItemToArray(array, item);
		}
	}
}

static int do_case_list(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* projectid = cJSON_GetObjectItem(root, "project_id");

	cJSON* array = cJSON_CreateArray();
	if (array == NULL)
		return -2;
	cJSON_AddItemToObject(res, "data", array);

#ifdef __WINDOWS__
	intptr_t hFile = 0;
	struct _finddata_t fileinfo;
	char file[256] = { 0x0 };
	snprintf(file, sizeof(file), "%s/*", CasePath);
	if ((hFile = _findfirst(file, &fileinfo)) != -1){
		do{
			if ((fileinfo.attrib & _A_SUBDIR)) continue;
			add_to_databse_filelist(array, projectid, fileinfo.name);
		} while (_findnext(hFile, &fileinfo) == 0);
		_findclose(hFile);
	}
#else
	DIR* dir;
	struct    dirent* ptr;
	if ((dir = opendir(CasePath)) != NULL){
		while ((ptr = readdir(dir)) != NULL){
			if (ptr->d_type == DT_REG || ptr->d_type == DT_UNKNOWN){
				add_to_databse_filelist(array, projectid, ptr->d_name);
			}
		}
		closedir(dir);
	}
#endif
	return 0;
}

static int do_proxy_database_change(HSOCKET hsock, cJSON* res, const char* dbfile, int projectid, const char* project, const char* des)
{
	sqlite3* dbConn;
	char fullpath[256] = { 0x0 };
	snprintf(fullpath, sizeof(fullpath), "%s/%s", CasePath, dbfile);
	sqlite3_open(fullpath, &dbConn);
	case_info_update(dbConn, projectid, project, des);
	sqlite3_close(dbConn);
	return 0;
}

static int do_case_save(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* dbfile = cJSON_GetObjectItem(root, "db_file");
	cJSON* projectid = cJSON_GetObjectItem(root, "project_id");
	cJSON* text = cJSON_GetObjectItem(root, "des");
	if (!projectid || !text || !cJSON_IsNumber(projectid) || !cJSON_IsString(text))
		return -1;

	char key[4] = { 0x0 };
	snprintf(key, sizeof(key), "%d", projectid->valueint);
	const char* proname = config_get_string_value("project", key, NULL);
	if (!proname) return 103;

	if (dbfile && cJSON_IsString(dbfile))
		return do_proxy_database_change(hsock, res, dbfile->valuestring, projectid->valueint, proname, text->valuestring);

	char dbname[64] = { 0x0 };
	create_case_name(projectid->valueint, dbname, sizeof(dbname));
	if (default_case_change_name(dbname) == false)
		return -3;

	sqlite3* dbConn;
	char fullpath[256] = { 0x0 };
	snprintf(fullpath, sizeof(fullpath), "%s/%s", CasePath, dbname);
	sqlite3_open(fullpath, &dbConn);
	case_info_update(dbConn, projectid->valueint, proname, text->valuestring);
	sqlite3_close(dbConn);
	return 0;
}

static int do_case_delete(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* dbfile = cJSON_GetObjectItem(root, "db_file");
	if (dbfile == NULL || dbfile->type != cJSON_String)
		return -1;

	if (strcmp(dbfile->valuestring, record_database) == 0)
		return -3;

	char fullpath[256] = { 0x0 };
	snprintf(fullpath, sizeof(fullpath), "%s/%s", CasePath, dbfile->valuestring);
	int ret = remove(fullpath);
	if (ret != 0)
		return -3;
	return 0;
}

static int do_case_step_view(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* case_file = cJSON_GetObjectItem(root, "case_file");
	cJSON* index = cJSON_GetObjectItem(root, "index");
	cJSON* count = cJSON_GetObjectItem(root, "count");
	if (!case_file|| !cJSON_IsString(case_file) || !index || !cJSON_IsNumber(index) || !count || !cJSON_IsNumber(count))
		return -1;

	cJSON* array = cJSON_CreateArray();
	cJSON_AddItemToObject(res, "data", array);

	sqlite3* dbConn;
	char fullpath[256] = { 0x0 };
	snprintf(fullpath, sizeof(fullpath), "%s/%s", CasePath, case_file->valuestring);
	sqlite3_open(fullpath, &dbConn);

	char dst_sql[4096] = { 0x0 };
	int	dst_len = 0;
	const char* sql_union = " union ";

	const char* sql = "select name from sqlite_sequence";
	sqlite3_stmt* stmt = NULL;
	int result = sqlite3_prepare_v2(dbConn, sql, -1, &stmt, NULL);
	if (result == SQLITE_OK){
		while (sqlite3_step(stmt) == SQLITE_ROW){
			const char* table = (const char*)sqlite3_column_text(stmt, 0);
			if (strncmp(table, "record_", 7) != 0) continue;
			const char* need_union = "";
			if (dst_len != 0)
				need_union = sql_union;
			dst_len += snprintf(dst_sql + dst_len, sizeof(dst_sql) - dst_len, "%sselect recordtime, event_type, protocol, ip, port, content, note from %s where event_type < 3", need_union, table);
		}
		if (dst_len)
			snprintf(dst_sql + dst_len, sizeof(dst_sql) - dst_len, " order by recordtime limit %d,%d", index->valueint, count->valueint);
	}
	sqlite3_finalize(stmt);

	size_t bufsz = 4096;
	char* buf = (char*)malloc(bufsz);
	stmt = NULL;
	result = sqlite3_prepare_v2(dbConn, dst_sql, -1, &stmt, NULL);
	if (result == SQLITE_OK){
		while (sqlite3_step(stmt) == SQLITE_ROW){
			long long timestamp =  sqlite3_column_int64(stmt, 0);
			long long event = sqlite3_column_int64(stmt, 1);
			long long protocol = sqlite3_column_int64(stmt, 2);
			const char* host = (const char*)sqlite3_column_text(stmt, 3);
			long long port = sqlite3_column_int64(stmt, 4);
			const char* content = (const char*)sqlite3_column_text(stmt, 5);
			const char* note = (const char*)sqlite3_column_text(stmt, 6);
			size_t newsz = strlen(content)+ strlen(note) + 64;
			if (newsz > bufsz) {
				bufsz = bufsz * 2;
				buf = (char*)realloc(buf, bufsz);
			}
			snprintf(buf, bufsz, "%lld|%lld|%lld|%s:%lld|%s|%s", timestamp, event, protocol, host, port, content, note);
			cJSON_AddItemToArray(array, cJSON_CreateString(buf));
		}
	}
	free(buf);
	sqlite3_finalize(stmt);
	sqlite3_close(dbConn);
	return 0;
}

static int do_case_rename(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* dbfile = cJSON_GetObjectItem(root, "db_file");
	cJSON* newname = cJSON_GetObjectItem(root, "new_name");
	if (dbfile == NULL || newname == NULL || dbfile->type != cJSON_String || newname->type != cJSON_String)
		return -1;

	if (strcmp(dbfile->valuestring, record_database) == 0)
	{
		if (default_case_change_name(newname->valuestring) == false)
			return -3;
	}
	else
	{
		char oldfile[256] = { 0x0 };
		char newfile[256] = { 0x0 };
		snprintf(oldfile, sizeof(oldfile), "%s/%s", CasePath, dbfile->valuestring);
		snprintf(newfile, sizeof(newfile), "%s/%s", CasePath, newname->valuestring);
		int ret = rename(oldfile, newfile);
		if (ret != 0)
			return -3;
	}
	return 0;
}

static int do_case_info_update(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* dbfile = cJSON_GetObjectItem(root, "db_file");
	cJSON* project_id = cJSON_GetObjectItem(root, "project_id");
	cJSON* des = cJSON_GetObjectItem(root, "des");
	if (dbfile == NULL || des == NULL || dbfile->type != cJSON_String || des->type != cJSON_String)
		return -1;
	const char* pro_name = get_project_name_by_project_id(project_id->valueint);
	char full_path[256] = { 0x0 };
	snprintf(full_path, sizeof(full_path), "%s/%s", CasePath, dbfile->valuestring);

	sqlite3* db_conn;
	sqlite3_open(full_path, &db_conn);
	case_info_update(db_conn, project_id->valueint, pro_name, des->valuestring);
	sqlite3_close(db_conn);
	return 0;
}

static int do_case_create(HSOCKET hsock, cJSON* root, cJSON* res) {
	cJSON* project_id = cJSON_GetObjectItem(root, "project_id");
	cJSON* des = cJSON_GetObjectItem(root, "des");
	if (!project_id || !des || !cJSON_IsNumber(project_id) || !cJSON_IsString(des)) return ERROR_PRAM;

	const char* pro_name = get_project_name_by_project_id(project_id->valueint);
	char case_name[64] = { 0x0 };
	create_case_name(project_id->valueint, case_name, sizeof(case_name));
	char full_path[256] = { 0x0 };
	snprintf(full_path, sizeof(full_path), "%s/%s", CasePath, case_name);

	sqlite3* db_conn;
	sqlite3_open(full_path, &db_conn);
	case_info_init(db_conn, project_id->valueint, pro_name, des->valuestring);
	sqlite3_close(db_conn);
	cJSON_AddStringToObject(res, "case_name", case_name);
	return 0;
}

static int do_case_step_add(HSOCKET hsock, cJSON* root, cJSON* res) {
	cJSON* case_name = cJSON_GetObjectItem(root, "case_name");
	cJSON* time = cJSON_GetObjectItem(root, "recordtime");
	cJSON* event = cJSON_GetObjectItem(root, "event_type");
	cJSON* protocol = cJSON_GetObjectItem(root, "protocol");
	cJSON* host = cJSON_GetObjectItem(root, "host");
	cJSON* port = cJSON_GetObjectItem(root, "port");
	cJSON* sessionid = cJSON_GetObjectItem(root, "sessionid");
	cJSON* msg = cJSON_GetObjectItem(root, "content");
	cJSON* note = cJSON_GetObjectItem(root, "note");
	if (!case_name || !time || !event || !protocol || !host || !port || !sessionid || !msg || !note ||
		!cJSON_IsString(case_name) || !cJSON_IsString(time) || !cJSON_IsNumber(event) || !cJSON_IsNumber(protocol) ||
		!cJSON_IsString(host) || !cJSON_IsNumber(port) || !cJSON_IsNumber(sessionid) || !cJSON_IsString(msg))
		return ERROR_PRAM;

	int nlen = 0;
	char* note_str = NULL;
	if (cJSON_IsString(note)) {
		note_str = note->valuestring;
		nlen = (int)strlen(note->valuestring);
	}
	else {
		note_str = cJSON_PrintUnformatted(note, &nlen);
	}
		
	char full_path[256] = { 0x0 };
	snprintf(full_path, sizeof(full_path), "%s/%s", CasePath, case_name->valuestring);

	sqlite3* db_conn;
	sqlite3_open(full_path, &db_conn);
	case_append(db_conn, atoll(time->valuestring), event->valueint, protocol->valueint, host->valuestring, port->valueint, sessionid->valueint, msg->valuestring, (int)strlen(msg->valuestring), note_str, nlen);
	sqlite3_close(db_conn);
	if (!cJSON_IsString(note))cJSON_free(note_str);
	return 0;
}

static int do_project_config(HSOCKET hsock, cJSON* root, cJSON* res) {
	cJSON* array = cJSON_CreateArray();
	if (NULL == array)
		return -2;
	cJSON_AddItemToObject(res, "data", array);

	t_project_config* info;
	int project_size = int(ProjectConfig.size());
	for (int i = 0; i < project_size; i++) {
		info = ProjectConfig[i];
		cJSON* item = cJSON_CreateObject();
		if (NULL == item)
			break;
		cJSON_AddNumberToObject(item, "id", i);
		cJSON_AddStringToObject(item, "name", info->name.c_str());
		cJSON_AddStringToObject(item, "parms", info->parms.c_str());
		
		cJSON* groupids = cJSON_CreateArray();
		cJSON_AddItemToObject(item, "group_ids", groupids);
		
		std::map<std::string, t_agent_group*>::iterator iter;
		for (iter = info->groups.begin(); iter != info->groups.end(); ++iter) {
			cJSON_AddItemToArray(groupids, cJSON_CreateString(iter->first.c_str()));
		}

		cJSON_AddItemToArray(array, item);
	}
	return 0;
}

static int do_sync_files(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* project = cJSON_GetObjectItem(root, "project_id");

	t_project_config* projectcfg;
	t_agent_group* group;
	std::map<std::string, t_agent_group*>::iterator iter_group;
	std::map<HSOCKET, t_sheeps_agent*>::iterator iter_agent;
	for (int i = 0; i != int(ProjectConfig.size()); ++i) {
		if (project && cJSON_IsNumber(project) && project->valueint != i)
			continue;

		projectcfg = ProjectConfig[i];
		for (iter_group = projectcfg->groups.begin(); iter_group != projectcfg->groups.end(); ++iter_group) {
			group = iter_group->second;
			for (iter_agent = group->agents->begin(); iter_agent != group->agents->end(); ++iter_agent) {
				iter_agent->second->ready = AGENT_AUTH;
				sync_files(iter_agent->first, iter_agent->second->projectid);
			}
		}
	}
	return 0;
}

static int do_task_report_info(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* task_id = cJSON_GetObjectItem(root, "task_id");
	if (!task_id || !cJSON_IsNumber(task_id)) return ERROR_PRAM;

	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(task_id->valueint);
	if (!taskcfg) return ERROR_TASK_NOT_EXIST;
	hServerTaskRun taskrun = taskcfg->taskrun;
	if (!taskrun) return ERROR_TASK_NOT_EXIST;

	cJSON* data = cJSON_AddObjectToObject(res, "data");

	//status
	cJSON_AddNumberToObject(data, "state", taskcfg->taskState);
	cJSON_AddNumber64ToObject(data, "start_time", taskrun->StartTime);

	//simple info
	int max_online = taskcfg->loopMode == 0 ? taskcfg->totalUser : taskcfg->onceUser * (taskrun->case_time_len/taskcfg->spaceTime + 1);
	max_online = taskcfg->totalUser < max_online ? taskcfg->totalUser : max_online;

	cJSON_AddNumberToObject(data, "case_step_len", taskrun->pushmsg.startRow);
	cJSON_AddNumberToObject(data, "case_time_len", taskrun->case_time_len);
	cJSON_AddNumberToObject(data, "max_online", max_online);
	cJSON_AddNumberToObject(data, "run_success", taskrun->run_success);
	cJSON_AddNumberToObject(data, "run_failed", taskrun->run_failed);

	//online
	cJSON* online = cJSON_CreateObject();
	cJSON_AddItemToObject(data, "online", online);
	int total = (int)taskrun->online.vecData->size();
	cJSON_AddNumberToObject(online, "total", total);

	//error
	cJSON* error = cJSON_CreateObject();
	cJSON_AddItemToObject(data, "error", error);
	total = (int)taskrun->error.vecData->size();
	cJSON_AddNumberToObject(error, "total", total);

	//connect
	cJSON* connect = cJSON_CreateObject();
	cJSON_AddItemToObject(data, "connect", connect);
	total = (int)taskrun->connect.vecData->size();
	cJSON_AddNumberToObject(connect, "total", total);

	//net
	cJSON* net = cJSON_CreateObject();
	cJSON_AddItemToObject(data, "net", net);
	total = (int)taskrun->netpack.vecData->size();
	cJSON_AddNumberToObject(net, "total", total);

	//counter
	cJSON* counter = cJSON_CreateObject();
	cJSON_AddItemToObject(data, "custom", counter);
	total = (int)taskrun->counter.vecData->size();
	cJSON_AddNumberToObject(counter, "total", total);

	return ERROR_OK;
}

static int do_task_report_online(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* task_id = cJSON_GetObjectItem(root, "task_id");
	cJSON* index = cJSON_GetObjectItem(root, "index");
	cJSON* count = cJSON_GetObjectItem(root, "count");
	if (!task_id || !index || !count || !cJSON_IsNumber(task_id) ||!cJSON_IsNumber(index) || !cJSON_IsNumber(count)) return ERROR_PRAM;

	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(task_id->valueint);
	if (!taskcfg) return ERROR_TASK_NOT_EXIST;
	hServerTaskRun taskrun = taskcfg->taskrun;
	if (!taskrun) return ERROR_TASK_NOT_EXIST;

	std::vector<std::string>* online = taskrun->online.vecData;
	int total = (int)online->size();
	int get_index = index->valueint;
	if (get_index < 0) get_index = 0;
	if (get_index >= total) return ERROR_INDEX_ERROR;

	int left = total - get_index;
	int get_count = count->valueint;
	if (get_count <= 0) {
		get_count = left;
	}
	else {
		get_count = left < get_count ? left : get_count;
	}
	int max_index = get_index + get_count;

	cJSON_AddNumberToObject(res, "size", total);
	cJSON_AddNumberToObject(res, "count", get_count);
	cJSON_AddNumberToObject(res, "next", max_index);
	cJSON* array = cJSON_CreateArray();
	if (!array) return ERROR_MEMRAY;
	cJSON_AddItemToObject(res, "data", array);
	for (int i = get_index; i < max_index; ++i) {
		cJSON_AddItemToArray(array, cJSON_CreateString( (*online)[i].c_str() ));
	}
	return ERROR_OK;
}

static int do_task_report_error(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* task_id = cJSON_GetObjectItem(root, "task_id");
	cJSON* index = cJSON_GetObjectItem(root, "index");
	cJSON* count = cJSON_GetObjectItem(root, "count");
	if (!task_id || !index || !count || !cJSON_IsNumber(task_id) || !cJSON_IsNumber(index) || !cJSON_IsNumber(count)) return ERROR_PRAM;

	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(task_id->valueint);
	if (!taskcfg) return ERROR_TASK_NOT_EXIST;
	hServerTaskRun taskrun = taskcfg->taskrun;
	if (!taskrun) return ERROR_TASK_NOT_EXIST;

	std::vector<std::string>* error = taskrun->error.vecData;
	int total = (int)error->size();
	int get_index = index->valueint;
	if (get_index < 0) get_index = 0;
	if (get_index >= total) return ERROR_INDEX_ERROR;

	int left = total-get_index;
	int get_count = count->valueint;
	if (get_count <= 0) {
		get_count = left;
	}
	else {
		get_count = left < get_count ? left : get_count;
	}
	int max_index = get_index + get_count;

	cJSON_AddNumberToObject(res, "size", total);
	cJSON_AddNumberToObject(res, "count", get_count);
	cJSON_AddNumberToObject(res, "next", max_index);
	cJSON* array = cJSON_CreateArray();
	if (!array) return ERROR_MEMRAY;
	cJSON_AddItemToObject(res, "data", array);
	
	for (int i = get_index; i < max_index; ++i) {
		cJSON_AddItemToArray(array, cJSON_CreateString((*error)[i].c_str()));
	}
	return ERROR_OK;
}

static int do_task_report_connect(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* task_id = cJSON_GetObjectItem(root, "task_id");
	cJSON* index = cJSON_GetObjectItem(root, "index");
	cJSON* count = cJSON_GetObjectItem(root, "count");
	if (!task_id || !index || !count || !cJSON_IsNumber(task_id) || !cJSON_IsNumber(index) || !cJSON_IsNumber(count)) return ERROR_PRAM;

	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(task_id->valueint);
	if (!taskcfg) return ERROR_TASK_NOT_EXIST;
	hServerTaskRun taskrun = taskcfg->taskrun;
	if (!taskrun) return ERROR_TASK_NOT_EXIST;

	std::vector<std::string>* connect = taskrun->connect.vecData;
	int total = (int)connect->size();
	int get_index = index->valueint;
	if (get_index < 0) get_index = 0;
	if (get_index >= total) return ERROR_INDEX_ERROR;

	int left = total - get_index;
	int get_count = count->valueint;
	if (get_count <= 0) {
		get_count = left;
	}
	else {
		get_count = left < get_count ? left : get_count;
	}
	int max_index = get_index + get_count;

	cJSON_AddNumberToObject(res, "size", total);
	cJSON_AddNumberToObject(res, "count", get_count);
	cJSON_AddNumberToObject(res, "next", max_index);
	cJSON* array = cJSON_CreateArray();
	if (!array) return ERROR_MEMRAY;
	cJSON_AddItemToObject(res, "data", array);
	for (int i = get_index; i < max_index; ++i) {
		cJSON_AddItemToArray(array, cJSON_CreateString((*connect)[i].c_str()));
	}
	return ERROR_OK;
}

static int do_task_report_netflow(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* task_id = cJSON_GetObjectItem(root, "task_id");
	cJSON* index = cJSON_GetObjectItem(root, "index");
	cJSON* count = cJSON_GetObjectItem(root, "count");
	if (!task_id || !index || !count || !cJSON_IsNumber(task_id) || !cJSON_IsNumber(index) || !cJSON_IsNumber(count)) return ERROR_PRAM;

	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(task_id->valueint);
	if (!taskcfg) return ERROR_TASK_NOT_EXIST;
	hServerTaskRun taskrun = taskcfg->taskrun;
	if (!taskrun) return ERROR_TASK_NOT_EXIST;

	std::vector<std::string>* netpack = taskrun->netpack.vecData;
	int total = (int)netpack->size();
	int get_index = index->valueint;
	if (get_index < 0) get_index = 0;
	if (get_index >= total) return ERROR_INDEX_ERROR;

	int left = total - get_index;
	int get_count = count->valueint;
	if (get_count <= 0) {
		get_count = left;
	}
	else {
		get_count = left < get_count ? left : get_count;
	}
	int max_index = get_index + get_count;

	cJSON_AddNumberToObject(res, "size", total);
	cJSON_AddNumberToObject(res, "count", get_count);
	cJSON_AddNumberToObject(res, "next", max_index);
	cJSON* array = cJSON_CreateArray();
	if (!array) return ERROR_MEMRAY;
	cJSON_AddItemToObject(res, "data", array);
	for (int i = get_index; i < max_index; ++i) {
		cJSON_AddItemToArray(array, cJSON_CreateString((*netpack)[i].c_str()));
	}
	return ERROR_OK;
}

static int do_task_report_api(HSOCKET hsock, cJSON* root, cJSON* res) {
	cJSON* task_id = cJSON_GetObjectItem(root, "task_id");
	if (!task_id || !cJSON_IsNumber(task_id)) return ERROR_PRAM;

	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(task_id->valueint);
	if (!taskcfg) return ERROR_TASK_NOT_EXIST;
	hServerTaskRun taskrun = taskcfg->taskrun;
	if (!taskrun) return ERROR_TASK_NOT_EXIST;

	cJSON* array = cJSON_CreateArray();
	cJSON_AddItemToObject(res, "data", array);

	std::map<std::string, ReportInfoApi*>* api = taskrun->api;
	std::map<std::string, ReportInfoApi*>::iterator iter;
	for (iter = api->begin(); iter != api->end(); ++iter) {
		ReportInfoApi* info = iter->second;
		cJSON* item = cJSON_CreateObject();
		cJSON_AddStringToObject(item, "api", iter->first.c_str());
		if (info->send_count > 0) {
			cJSON_AddNumber64ToObject(item, "send_flow", info->send_flow);
			cJSON_AddNumberToObject(item, "send_count", info->send_count);
		}
		if (info->recv_count > 0) {
			cJSON_AddNumber64ToObject(item, "recv_flow", info->recv_flow);
			cJSON_AddNumberToObject(item, "recv_count", info->recv_count);
		}
		
		if (info->success || info->error) {
			cJSON_AddNumberToObject(item, "success", info->success);
			cJSON_AddNumberToObject(item, "error", info->error);
		}
		int size = info->sorted;
		if (size) {
			std::vector<int>* vec = info->vecData;
			cJSON_AddNumberToObject(item, "min", (*vec)[0]);
			cJSON_AddNumberToObject(item, "max", (*vec)[size - 1]);
			cJSON_AddNumberToObject(item, "10", (*vec)[int(size * 0.1)]);
			cJSON_AddNumberToObject(item, "20", (*vec)[int(size * 0.2)]);
			cJSON_AddNumberToObject(item, "30", (*vec)[int(size * 0.3)]);
			cJSON_AddNumberToObject(item, "40", (*vec)[int(size * 0.4)]);
			cJSON_AddNumberToObject(item, "50", (*vec)[int(size * 0.5)]);
			cJSON_AddNumberToObject(item, "60", (*vec)[int(size * 0.6)]);
			cJSON_AddNumberToObject(item, "70", (*vec)[int(size * 0.7)]);
			cJSON_AddNumberToObject(item, "80", (*vec)[int(size * 0.8)]);
			cJSON_AddNumberToObject(item, "90", (*vec)[int(size * 0.9)]);
		}
		cJSON_AddItemToArray(array, item);
	}
	return ERROR_OK;
}

static int do_task_report_api_info(HSOCKET hsock, cJSON* root, cJSON* res) {
	cJSON* task_id = cJSON_GetObjectItem(root, "task_id");
	cJSON* api_name = cJSON_GetObjectItem(root, "api");
	cJSON* index = cJSON_GetObjectItem(root, "index");
	cJSON* count = cJSON_GetObjectItem(root, "count");
	if (!task_id || !api_name || !cJSON_IsNumber(task_id) || !cJSON_IsString(api_name)) return ERROR_PRAM;

	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(task_id->valueint);
	if (!taskcfg) return ERROR_TASK_NOT_EXIST;
	hServerTaskRun taskrun = taskcfg->taskrun;
	if (!taskrun) return ERROR_TASK_NOT_EXIST;

	cJSON* array = cJSON_CreateArray();
	cJSON_AddItemToObject(res, "data", array);

	std::map<std::string, ReportInfoApi*>* api = taskrun->api;
	std::map<std::string, ReportInfoApi*>::iterator iter = api->find(api_name->valuestring);
	if (iter != api->end()) {
		ReportInfoApi* info = iter->second;
		int total = (int)info->vecData->size();
		int get_index = index->valueint;
		if (get_index < 0) get_index = 0;
		if (get_index >= total) return ERROR_INDEX_ERROR;

		int left = total - get_index;
		int get_count = count->valueint;
		if (get_count <= 0) {
			get_count = left;
		}
		else {
			get_count = left < get_count ? left : get_count;
		}
		int max_index = get_index + get_count;
		for (int i = get_index; i < max_index; ++i) {
			cJSON_AddItemToArray(array, cJSON_CreateNumber((*(info->vecData))[i]));
		}
	}
	return ERROR_OK;
}

static int do_task_report_custom(HSOCKET hsock, cJSON* root, cJSON* res)
{
	cJSON* task_id = cJSON_GetObjectItem(root, "task_id");
	cJSON* index = cJSON_GetObjectItem(root, "index");
	cJSON* count = cJSON_GetObjectItem(root, "count");
	if (!task_id || !index || !count || !cJSON_IsNumber(task_id) || !cJSON_IsNumber(index) || !cJSON_IsNumber(count)) return ERROR_PRAM;

	hServerTaskConfig taskcfg = get_server_taskcfg_by_id(task_id->valueint);
	if (!taskcfg) return ERROR_TASK_NOT_EXIST;
	hServerTaskRun taskrun = taskcfg->taskrun;
	if (!taskrun) return ERROR_TASK_NOT_EXIST;

	std::vector<std::string>* counter = taskrun->counter.vecData;
	int total = (int)counter->size();
	int get_index = index->valueint;
	if (get_index < 0) get_index = 0;
	if (get_index >= total) return ERROR_INDEX_ERROR;

	int left = total - get_index;
	int get_count = count->valueint;
	if (get_count <= 0) {
		get_count = left;
	}
	else {
		get_count = left < get_count ? left : get_count;
	}
	int max_index = get_index + get_count;

	cJSON_AddNumberToObject(res, "size", total);
	cJSON_AddNumberToObject(res, "count", get_count);
	cJSON_AddNumberToObject(res, "next", max_index);
	cJSON* array = cJSON_CreateArray();
	if (!array) return ERROR_MEMRAY;
	cJSON_AddItemToObject(res, "data", array);
	for (int i = get_index; i < max_index; ++i) {
		cJSON_AddItemToArray(array, cJSON_CreateString((*counter)[i].c_str()));
	}
	return ERROR_OK;
}

static int do_test_user_login(HSOCKET hsock, cJSON* root, cJSON* res){
	cJSON* username = cJSON_GetObjectItem(root, "username");
	cJSON* password = cJSON_GetObjectItem(root, "password");

	if (!username || !cJSON_IsString(username) || !password || !cJSON_IsString(password)){
		return ERROR_PRAM;
	}
	if ((strcmp(username->valuestring, "admin") != 0) || (strcmp(password->valuestring, "123456") != 0) ){
		return ERROR_PASSWORD;
	}
	cJSON_AddStringToObject(res, "token", "token_string");
	return ERROR_OK;
}

static int do_test_user_info(HSOCKET hsock, cJSON* root, cJSON* res){
	cJSON* token = cJSON_GetObjectItem(root, "token");
	if (!token || !cJSON_IsString(token)){
		return ERROR_PRAM;
	}
	if (strcmp(token->valuestring, "token_string") != 0 ){
		return ERROR_TOKEN;
	}
	cJSON_AddStringToObject(res, "username", "admin");
	cJSON_AddStringToObject(res, "sex", "男");
	cJSON_AddStringToObject(res, "age", "25");
	return ERROR_OK;
}

static int do_test_user_logout(HSOCKET hsock, cJSON* root, cJSON* res){
	cJSON* token = cJSON_GetObjectItem(root, "token");

	if (!token || !cJSON_IsString(token)){
		return ERROR_PRAM;
	}
	if (strcmp(token->valuestring, "token_string") != 0 ){
		return ERROR_TOKEN;
	}
	//cJSON_AddStringToObject(res, "token", "token_string");
	return ERROR_OK;
}

std::map<std::string, serverConsole_cmd_cb> ConsoleFunc{
	{std::string("/api/agent_list"),	do_agent_list},		//受控端列表

	{std::string("/api/task_group"),	do_console_task_group},		//修改执行组
	{std::string("/api/task_log_level"),do_console_task_log_level},		//修改受控端日志等级
	{std::string("/api/task_create"),	do_console_task_create},	//创建任务
	{std::string("/api/task_info"),		do_console_task_info},		//任务信息
	{std::string("/api/task_user"),		do_console_task_user},		//增减任务人数
	{std::string("/api/task_delete"),	do_console_task_delete},	//删除任务
	{std::string("/api/task_list"),		do_console_task_list},		//任务列表
	{std::string("/api/task_run"),		do_console_task_run},		//任务开始
	{std::string("/api/task_stop"),		do_console_task_stop},		//任务停止

	{std::string("/api/proxy_list"),	do_proxy_addr_list},		//代理列表
	{std::string("/api/proxy_report_api"), do_proxy_report_api},

	{std::string("/api/case_record"),	do_case_record_chang},		//是否录制
	{std::string("/api/case_record_set_filter"), do_case_record_set_filter},
	{std::string("/api/case_record_get_filter"), do_case_record_get_filter},
	{std::string("/api/case_addr_list"),do_case_addr_list},			//db内录制表
	{std::string("/api/case_addr_delete"), do_case_addr_delete},	//删除db录制表
	{std::string("/api/case_list"),		do_case_list},				//db文件列表
	{std::string("/api/case_save"),		do_case_save},				//用例保存
	{std::string("/api/case_delete"),	do_case_delete},			//删除db
	{std::string("/api/case_rename"),	do_case_rename},			//db改名
	{std::string("/api/case_info_update"), do_case_info_update},

	{std::string("/api/case_create"),	do_case_create},			//创建用例
	{std::string("/api/case_view"),		do_case_step_view},			//查看用例步骤
	{std::string("/api/case_append"),	do_case_step_add},			//写入用例步骤

	{std::string("/api/project_config"),do_project_config},			//项目配置
	{std::string("/api/sync_files"),	do_sync_files},

	{std::string("/api/report_info"),	do_task_report_info},
	{std::string("/api/report_online"), do_task_report_online},
	{std::string("/api/report_error"),	do_task_report_error},
	{std::string("/api/report_connect"),do_task_report_connect},
	{std::string("/api/report_net"),	do_task_report_netflow},
	{std::string("/api/report_api"),	do_task_report_api},
	{std::string("/api/report_api_info"),	do_task_report_api_info},
	{std::string("/api/report_custom"),	do_task_report_custom},

	{std::string("/test/login"),		do_test_user_login},
	{std::string("/test/userinfo"),		do_test_user_info},
	{std::string("/test/logout"),		do_test_user_logout}
};

static void server_hook_bind(HSOCKET hsock, BaseWorker* user, void* data, int state) {
	if (state == 0){
		ServerHookProtocol* hook = (ServerHookProtocol*)user;
		hook->http_handler(hsock, hsock->recv_buf, hsock->offset);
	}
}

static int http_callback(HSOCKET hsock, const char* data, int len){
	if (server_hook) {
		HsocketRebindWorker(hsock, (BaseWorker*)server_hook, NULL, server_hook_bind);
		return 0;
	}
	return -1;
}

static int do_request_by_uri(HSOCKET hsock, char* uri, const char* body, int clen){
	std::map<std::string, serverConsole_cmd_cb>::iterator iter = ConsoleFunc.find(uri);
	if (iter != ConsoleFunc.end()) {
		cJSON* req = cJSON_ParseByte(body, clen);
		cJSON* res = cJSON_CreateObject();
		if (!req || !res) {
			if (req) cJSON_Delete(req);
			if (res) cJSON_Delete(res);
			return -1;
		}
		int ret = iter->second(hsock, req, res);
		send_console_msg(hsock, res, ret);
		cJSON_Delete(req);
		cJSON_Delete(res);
		return 0;
	}
	return 1;
}

static int get_content_length(const char* http_stream){
	const char* k = "Content-Length: ";
	char v[32] = { 0x0 };
	char* t = strstr((char*)http_stream, k);
	if (t == NULL)
		return 0;

	char* e = strstr(t, "\r\n");
	if (e == NULL)
		return 0;
	*e = 0x0;

	snprintf(v, sizeof(v), "%s", t + strlen(k));
	*e = '\r';
	return atoi(v);
}

static int get_uri_string(const char* http_stream, char* buff, size_t bufflen){
	const char* p = strstr(http_stream, " ");
	if (p == NULL)
		return -1;
	p++;
	const char* e = strstr(p, " ");
	if (e == NULL)
		return -1;
	const char* s = strstr(p, "?");
	size_t len = 0;
	if (s == NULL || s > e)
		len = e - p;
	else
		len = s - p;
	if (len >= bufflen)
		return -1;
	memcpy(buff, p, len);
	return 0;
}

int CheckHttpRequest(HSOCKET hsock, ServerProtocol* proto, const char* data, int len)
{
	if (len < 4)
		return 0;
	const char* p = strstr(data, "\r\n\r\n");
	if (p == NULL)
		return 0;
	int hlen = int(p + 4 - data);
	int clen = get_content_length(data);
	if (len < hlen + clen)
		return 0;

	char uri[256] = { 0x0 };
	if (get_uri_string(data, uri, sizeof(uri))) {
		HsocketClose(hsock);
		return 0;
	}
	urldecode((unsigned char*)uri, (unsigned char*)uri);

	char peerip[40] = { 0x0 };
	int peerport = 0;
	HsocketPeerAddr(proto->initSock, peerip, sizeof(peerip), &peerport);
	LOG(slogid, LOG_FAULT, "%s:%d %s:%d %s\n", __func__, __LINE__, peerip, peerport, uri);

	if (strncasecmp(uri, "http://", 7) == 0 && proxy_open)
		return do_http_proxy(hsock, proto, uri+7, data, len);
	if (strncasecmp(data, "CONNECT", 7) == 0 && proxy_open)
		return do_https_proxy(hsock, proto, uri, data, len);

	int ret = 1;
	if (strncasecmp(data, "GET", 3) == 0) {
		ret = get_static_file(hsock, uri);
	}
	else if (strncasecmp(data, "POST", 4) == 0) {
		ret = do_request_by_uri(hsock, uri, p +4, clen);
	}
	if (ret > 0) {
		return http_callback(hsock, data, len);
	}
	HsocketClose(hsock);
	return 0;
}